<template>
  <div>
    <!-- 用户搜索 -->
    <el-card shadow="always" style="height: 80px">
      <el-form :inline="true" class="form">
        <el-form-item label="用户名：" style="width: 40%">
          <el-input
            placeholder="请输入搜索的用户名"
            v-model="keyWord"
          ></el-input>
        </el-form-item>
        <!-- 搜索和重置按钮 -->
        <el-form-item>
          <el-button
            type="primary"
            :disabled="keyWord ? false : true"
            @click="searchUser"
          >
            搜索
          </el-button>
          <el-button @click="RefreshUser">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 用户添加和删除 -->
    <el-card>
      <!-- 按钮 -->
      <el-button type="primary" @click="addUser">添加用户</el-button>
      <el-button
        type="danger"
        :disabled="delUserArr.length ? false : true"
        @click="delSelect"
      >
        批量删除
      </el-button>
      <!-- 内容表格 -->
      <!-- selection-change	当选择项发生变化时会触发该事件 -->
      <el-table
        style="margin: 10px 0"
        border
        :data="userArr"
        @selection-change="selectChange"
      >
        <el-table-column
          type="selection"
          align="center"
          width="50px"
        ></el-table-column>
        <el-table-column
          label="#"
          align="center"
          type="index"
        ></el-table-column>
        <el-table-column label="id" align="center" prop="id"></el-table-column>
        <el-table-column
          label="用户名字"
          align="center"
          prop="username"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="用户名称"
          align="center"
          prop="name"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="用户角色"
          align="center"
          prop="roleName"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="更新时间"
          align="center"
          prop="updateTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column label="操作" width="300px" align="center">
          <template #="{ row, $index }">
            <el-button plain icon="User" size="small" @click="shareUser(row)">
              分配角色
            </el-button>
            <el-button
              type="primary"
              icon="Edit"
              size="small"
              @click="changeUser(row)"
            >
              编辑
            </el-button>
            <!-- 删除按钮 添加弹窗 -->
            <el-popconfirm
              :title="`你确定要删除${userParams.username}吗？`"
              @confirm="deleteUser(row.id)"
            >
              <template #reference>
                <el-button type="danger" icon="Delete" size="small">
                  删除
                </el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页器 -->
      <el-pagination
        v-model:current-page="pageNow"
        v-model:page-size="pageSize"
        :page-sizes="[5, 7, 9, 11]"
        :background="true"
        layout="prev, pager, next, jumper, ->, sizes, total"
        :total="total"
        @size-change="handler"
        @current-change="getHasUser"
      />
      <!-- 新增用户和修改用户 抽屉部分的结构 -->
      <el-drawer v-model="drawer" size="30%">
        <template #header>
          <h4>{{ userParams.id ? '编辑用户' : '添加用户' }}</h4>
        </template>
        <template #default>
          <div>
            <!-- prop: 是要校验的名称  和 :model绑定的有关联 是它绑定里的子元素 -->
            <el-form :model="userParams" :rules="rules" ref="formRef">
              <el-form-item label="用户姓名" prop="username">
                <el-input
                  placeholder="输入用户姓名"
                  v-model="userParams.username"
                />
              </el-form-item>
              <el-form-item label="用户昵称" prop="name">
                <el-input
                  placeholder="输入用户昵称"
                  v-model="userParams.name"
                />
              </el-form-item>
              <el-form-item
                label="用户密码"
                prop="password"
                v-if="!userParams.id"
              >
                <el-input
                  placeholder="输入用户密码"
                  v-model="userParams.password"
                />
              </el-form-item>
            </el-form>
          </div>
        </template>
        <template #footer>
          <div style="flex: auto">
            <el-button @click="cancel">取消</el-button>
            <el-button type="primary" @click="save">确认</el-button>
          </div>
        </template>
      </el-drawer>
      <!-- 分配角色 抽屉部分的结构 -->
      <el-drawer v-model="drawer2" size="30%">
        <template #header>
          <h4>分配角色用户</h4>
        </template>
        <template #default>
          <div>
            <!-- prop: 是要校验的名称  和 :model绑定的有关联 是它绑定里的子元素 -->
            <el-form>
              <el-form-item label="用户姓名">
                <el-input v-model="userParams.username" disabled />
              </el-form-item>
              <el-form-item label="角色列表">
                <el-checkbox
                  v-model="checkAll"
                  :indeterminate="isIndeterminate"
                  @change="handleCheckAllChange"
                >
                  全选
                </el-checkbox>
                <el-checkbox-group
                  v-model="userRole"
                  @change="handleCheckedCitiesChange"
                >
                  <el-checkbox
                    v-for="(role, index) in allRole"
                    :key="index"
                    :label="role"
                  >
                    {{ role.roleName }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-form>
          </div>
        </template>
        <template #footer>
          <div style="flex: auto">
            <el-button @click="cancelClick">取消</el-button>
            <el-button type="primary" @click="saveClick">确认</el-button>
          </div>
        </template>
      </el-drawer>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, nextTick } from 'vue'
import {
  requserList,
  reqAddOrUpdateUser,
  reqALLRole,
  reqSetRole,
  reqDelUser,
  reqSelectUser,
} from '@/api/acl/user/index'
import type {
  Records,
  userListResponseData,
  User,
  AllRole,
  SetRole,
} from '@/api/acl/user/type'
import { ElMessage } from 'element-plus'
import useLayOutSettingStore from '@/store/modules/setting'
// 默认当前页数
const pageNow = ref<number>(1)
// 默认当前每页页数
const pageSize = ref<number>(5)
// 存储用户总数量
const total = ref<number>(0)
// 存储用户的信息的数组
const userArr = ref<Records>([])
// 给添加和编辑用户 抽屉绑定一个事件名
const drawer = ref<boolean>(false)
// 获取抽屉里表单校验的 form实例
const formRef = ref<any>()
// 存储table表格 复选框选中的数据
const delUserArr = ref<User[]>([])
// 获取小仓库更新值的变化
const settingStore = useLayOutSettingStore()

// 接收获取到的用户信息 就是抽屉列表里的信息
const userParams = reactive<User>({
  username: '',
  name: '',
  password: '',
})
// 获取用户的信息列表  默认传参页为1
const getHasUser = async (pager = 1) => {
  // 收集当前页的页码
  pageNow.value = pager
  // y因为接口要携带三个参数 第几页 一页几条数据 以及用户名
  let res: userListResponseData = await requserList(
    pageNow.value,
    pageSize.value,
    keyWord.value,
  )
  // console.log(res);
  if (res.code == 200) {
    userArr.value = res.data.records
    total.value = res.data.total
  }
}
// 分页器下拉菜单回调  当点击每页多少条数据时 页面会跟随条数变化而展示
const handler = () => {
  getHasUser()
}
// 组件挂载完毕 就渲染所有用户的信息
onMounted(() => {
  getHasUser()
})
// 点击添加用户 触发的事件
const addUser = () => {
  // 抽屉打开展示
  drawer.value = true
  // 每次添加的时候要保证上一次在抽屉里写的东西被清除
  Object.assign(userParams, {
    username: '',
    name: '',
    password: '',
    id: 0, //因为编辑的时候会存有id  所以这里也要清除掉
  })
  //先点击编辑按钮 再点击添加 会出现抽屉表单校验报错还存在的情况 因为第一次我们拿不到抽屉的form表单 是underfind 所以我们要点击的时候 先获取一下更新后的dom
  // 清除一下form表单的校验
  nextTick(() => {
    formRef.value.clearValidate('username')
    formRef.value.clearValidate('name')
    formRef.value.clearValidate('password')
  })
}
//  点击编辑按钮 触发的事件
const changeUser = async (row: User) => {
  drawer.value = true
  // 方法1.点击编辑按钮的时候 将该用户的 名字和昵称赋值给 抽屉里存放该数据的地方
  // userParams.username = row.username
  // userParams.name = row.name
  // 方法2.这个方法更好用 ：存储已有的账号信息
  Object.assign(userParams, row)
  nextTick(() => {
    formRef.value.clearValidate('username')
    formRef.value.clearValidate('name')
  })
}
// 抽屉标签 确认按钮的回调
const save = async () => {
  // 确认提交前 要对整个form表单进行校验 校验通过了 才继续往下调用接口
  // await formRef.value.validate()
  await formRef.value.validate()
  // 如果有id 就调用编辑接口 没有id  就是调用新增接口
  let res: any = await reqAddOrUpdateUser(userParams)
  // console.log(res);
  if (res.code == 200) {
    ElMessage({
      type: 'success',
      message: userParams.id ? '编辑成功' : '添加成功',
    })
    // 关闭抽屉
    drawer.value = false
    // 获取最新的全部账号信息
    getHasUser(userParams.id ? pageNow.value : 1) //有id 就是编辑那就留在当前页 否则去第一页
    // 浏览器页面自动刷新 不然编辑完用户信息 用户的名字都变化了 肯定要去登录页
    window.location.reload()
  } else {
    ElMessage({
      type: 'error',
      message: userParams.id ? '编辑失败' : '添加失败',
    })
  }
}
// 抽屉标签 取消按钮的回调
const cancel = () => {
  drawer.value = false
}
// 抽屉里 用户名的校验回调函数
const validateUsername = (rule: any, value: any, callback: any) => {
  if (value.trim().length >= 5) {
    callback()
  } else {
    callback(new Error('用户名长度不能小于5位'))
  }
}
// 抽屉里 名字的校验回调函数
const validateName = (rule: any, value: any, callback: any) => {
  if (value.trim().length >= 5) {
    callback()
  } else {
    callback(new Error('昵称长度不能小于5位'))
  }
}
// 抽屉里 密码的校验回调函数
const validatePassword = (rule: any, value: any, callback: any) => {
  if (value.trim().length >= 6) {
    callback()
  } else {
    callback(new Error('密码长度不能小于6位'))
  }
}
// 自定义校验规则
const rules = {
  username: [{ required: true, trigger: 'blur', validator: validateUsername }],
  name: [{ required: true, trigger: 'blur', validator: validateName }],
  password: [{ required: true, trigger: 'blur', validator: validatePassword }],
}
// -------------------------------------------------------------分配角色
// 给用户分配角色 抽屉绑定一个事件名
const drawer2 = ref<boolean>(false)
// 是否全选
const checkAll = ref<boolean>(false)
// 复选框 indeterminate	设置 indeterminate 状态，只负责样式控制
const isIndeterminate = ref<boolean>(false)
// 收集所有复选框内容
const allRole = ref<AllRole>([])
// 目前用户已经有的职位 默认勾上
const userRole = ref<AllRole>([])
// 分配角色按钮
const shareUser = async (row: User) => {
  //这个方法更好用 ：存储已有的账号信息
  Object.assign(userParams, row)
  // 获取到所有的职位和当前用户拥有的角色接口数据
  const res = await reqALLRole(userParams.id as number)
  console.log(res)
  if (res.code == 200) {
    // 全部职位角色
    allRole.value = res.data.allRolesList
    // 当前用户的角色
    userRole.value = res.data.assignRoles
  }
  // 点击展示抽屉
  drawer2.value = true
}
// 修改用户职位 的确认按钮 回调
const saveClick = async () => {
  // 先收集新增的职位数据
  let data: SetRole = {
    // 带着当前的用户id
    userId: userParams.id as number,
    // 收集当前用户新增职位的id
    roleIdList: userRole.value.map((item) => {
      return item.id as number
    }),
  }
  // 要将给用户添加的收集到的数据 提交出去
  const res = await reqSetRole(data)
  if (res.code == 200) {
    // 分配成功
    ElMessage({
      type: 'success',
      message: '分配成功',
    })
    // 关闭抽屉
    drawer2.value = false
    // 重新获取信息 且留在当前页
    getHasUser(pageNow.value)
  } else {
    ElMessage({
      type: 'error',
      message: '分配失败',
    })
  }
}
// 修改用户职位 的取消按钮 回调
const cancelClick = () => {
  drawer2.value = false
}
// 点击是否全选
const handleCheckAllChange = (val: boolean) => {
  // 如果点击全选了 就把所有的岗位给这个角色
  userRole.value = val ? allRole.value : []
  isIndeterminate.value = false
}
//  有一个没选 就不全选
const handleCheckedCitiesChange = (value: string[]) => {
  // 将所选中的职位 长度赋值给checkedCount
  const checkedCount = value.length
  // 如果所选中的职位长度  和全部职位长度一致 就全选框被选中
  checkAll.value = checkedCount === allRole.value.length
  // 反之 全选框状态则是未选中
  isIndeterminate.value =
    checkedCount > 0 && checkedCount < allRole.value.length
}
// 删除按钮
const deleteUser = async (userId: number) => {
  const res = await reqDelUser(userId)
  if (res.code == 200) {
    ElMessage({ type: 'success', message: '删除成功' })
    // 再重新获取数据，并且如果当前页删除完剩余的数据大于1 就留在当前页 否则就跳转到上一页
    getHasUser(userArr.value.length > 1 ? pageNow.value : pageNow.value - 1)
  }
}
// 当表格的复选框发生变化时 触发的事件 我们收集到当前变化项的用户对象  把id传给批量删除按钮
const selectChange = (value: any) => {
  delUserArr.value = value
}
// 批量删除
const delSelect = async () => {
  // 整理批量删除的参数
  const idsList: any = delUserArr.value.map((item) => {
    return item.id
  })
  // 批量删除接口请求
  const res: any = await reqSelectUser(idsList)
  if (res.code == 200) {
    ElMessage({ type: 'success', message: '批量删除成功' })
    getHasUser()
  }
}

// 用户搜索部分 根据关键字重新获取用户列表 需要带着用户的用户名称
// 声明一个 存储关键字的响应式数据 和搜索框绑定
const keyWord = ref<string>('')
// 搜索按钮重新访问用户列表 要带着query参数就是用户名
const searchUser = () => {
  getHasUser()
}
// 重置按钮  等于是将实例销毁重新创建 我们仓库里存的有之前写的刷新 监听值的变化来决定刷新
const RefreshUser = () => {
  settingStore.refresh = !settingStore.refresh
}
</script>

<style scoped lang="scss">
.form {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
